﻿#include"XQHttpRequest.h"
#include"QCoding.h"
#include"XQLog.hpp"
#include<QDateTime>
#include<QLocalSocket>
#include<QNetworkRequest>
#include<QNetworkAccessManager>
#include<QNetworkReply>
#include<QEventLoop>
#include<QTimer>
#include<QDebug>
XQHttpRequest::XQHttpRequest(QObject* parent)
	:QObject(parent)
{
	init();
}

XQHttpRequest::~XQHttpRequest()
{
	if (m_request != nullptr)
		delete m_request;
	if (m_reply != nullptr)
		m_reply->deleteLater();
	if (m_manager != nullptr)
		m_manager->deleteLater();
}

QString XQHttpRequest::url() const
{
	return m_request->url().toString();
}

bool XQHttpRequest::get(const QString& url)
{
	/*if (m_debug)
		XQDebug << QString("Get\r\nurl:%1\r\n").arg(url);*/
	setUrl(url);
	return get();
}

bool XQHttpRequest::get()
{
	// 发送HTTPS GET请求
	m_reply = m_manager->get(*m_request);
	if (m_reply != nullptr)
	{
		connect(m_reply, &QNetworkReply::finished, [=] {readyRead(); });
		connect(this, &QObject::destroyed, m_reply, &QObject::deleteLater);
		return true;
	}
	return false;
}

bool XQHttpRequest::post(const QString& url, const QByteArray& data)
{
	/*if(m_debug)
		XQDebug<<QString("Post\r\nurl:%1\r\ndata:\r\n%2").arg(url).arg(data);*/
	setUrl(url);
	if (m_request->header(QNetworkRequest::ContentTypeHeader).toString().isEmpty())
		m_request->setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
	return post(data);
}

bool XQHttpRequest::post(const QByteArray& data)
{
	// 发送POST请求
	m_reply = m_manager->post(*m_request, data);
	//qInfo() << m_request->rawHeaderList();
	if (m_reply != nullptr)
	{
		connect(m_reply, &QNetworkReply::finished, [=] {readyRead(); });
		connect(this, &QObject::destroyed, m_reply, &QObject::deleteLater);
		return true;
	}
	return false;
}

bool XQHttpRequest::post(const QString& url, const QJsonDocument& json)
{
	m_request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
	return post(url, json.toJson());
}

bool XQHttpRequest::wait(int timeout)
{
	if (m_reply == nullptr)
		return true;
	QDateTime start = QDateTime::currentDateTime();
	bool flag = true;
	QEventLoop loop;
	connect(this, &XQHttpRequest::finish, &loop, &QEventLoop::quit);
	if(timeout>0)
	{
		QTimer::singleShot(timeout, &loop, &QEventLoop::quit);//超时退出
	}
	loop.exec();
	if (start.msecsTo(QDateTime::currentDateTime()) >= timeout)
		flag = false;
	return flag;
}

void XQHttpRequest::clear_request()
{
	*m_request = QNetworkRequest();
}

QNetworkRequest* XQHttpRequest::request() const
{
	return m_request;
}

QString XQHttpRequest::toString()const
{
	return toByteArray();
}

QByteArray XQHttpRequest::toByteArray() const
{
	return m_data;
}

QVariantList XQHttpRequest::toList() const
{
	return QJsonDocument::fromJson(m_data).toVariant().toList();
}

QByteArray XQHttpRequest::Get(const QString& url, int timeout, bool toUtf8)
{
	XQHttpRequest http;
	if (!http.get(url))
		return QByteArray();
	if (!http.wait(timeout))
		return QByteArray();
	if (toUtf8)
		http.GbkToUtf8();
	return http.toByteArray();
}

bool XQHttpRequest::Post(const QString& url, const QByteArray& data, int timeout)
{
	XQHttpRequest http;
	if (!http.post(url, data))
		return false;
	if (!http.wait(timeout))
		return false;
	return true;
}

bool XQHttpRequest::Post(const QString& url, const QJsonDocument& json, int timeout)
{
	XQHttpRequest http;
	if (!http.post(url, json))
		return false;
	if (!http.wait(timeout))
		return false;
	return true;
}

QByteArray XQHttpRequest::Post_Reply( const QString& url, const QByteArray& data, int timeout, bool toUtf8)
{
	XQHttpRequest http;
	if (!http.post(url, data))
		return QByteArray();
	if (!http.wait(timeout))
		return QByteArray();
	if (toUtf8)
		http.GbkToUtf8();
	return http.toByteArray();
}

QByteArray XQHttpRequest::Post_Reply(const QString& url, const QJsonDocument& json, int timeout, bool toUtf8)
{
	XQHttpRequest http;
	if (!http.post(url, json))
		return QByteArray();
	if (!http.wait(timeout))
		return QByteArray();
	if (toUtf8)
		http.GbkToUtf8();
	return http.toByteArray();
}

void XQHttpRequest::setUrl(const QString& url)
{
	m_request->setUrl(QUrl(url));
}

void XQHttpRequest::GbkToUtf8()
{
	m_data = QCoding::GbkToUtf8(m_data);
}

void XQHttpRequest::init()
{
	if (m_request == nullptr)
	{
		m_request = new QNetworkRequest();
		// 设置SSL配置
		QSslConfiguration config = m_request->sslConfiguration();
		config.setProtocol(QSsl::TlsV1_2);
		m_request->setSslConfiguration(config);
	}
	if (m_manager == nullptr)
		m_manager = new QNetworkAccessManager(this);
}

void XQHttpRequest::readyRead()
{
	if (m_reply == nullptr)
		return;
	if (m_reply->error() != QNetworkReply::NoError) {
		emit error(m_reply->errorString());
		m_reply->deleteLater();
		m_reply = nullptr;
		return;
	}
	m_data = m_reply->readAll();
	m_reply->deleteLater();
	m_reply = nullptr;
	emit finish();
}
